/* 
    执行上下文作用域简称上下文
        变量和函数的上下文决定了他们可以访问哪些数据以及他们的行为。
        每个上下文都有一个关联的变量对象（variable Object），这个上下文中定义的所有变量和函数都存在于这个对象上。
        全局上下文是最外层的上下文。根据es实现的宿主环境，表示全局上下文的对象可能不一样。
        在浏览器中，全局上下文就是我们常说的window对象，因此所有通过var定义的全局变量和函数都会成为window的函数和方法。
        上下文在其所有代码执行完之后会被销毁，包括定义在它上面的所有变量和函数。
        注意：函数参数被认为是当前上下文中的变量，因此也跟上下文中的其他变量遵循相同的访问规则。
            扩展：this的使用指向
                箭头函数的this指向是定义箭头函数的父级this，其自己没有this，要捕获其所在上下文的this。
                普通函数如果直接调用或者未按照对象的方法调用，则this指向全局变量，如果是对象方法调用则是指向那个对象。
        4.2.1 作用域链增强
            try/catch语句的catch块
            with语句
        4.2.2 变量声明
            1.Var：在使用var声明变量时，变量会被自动的加入最接近的上下文中。在函数中，最近的上下文就是函数的局部上下文。在with语句中，最接近的上下文也是函数上下文。
                如果变量未经声明就初始化了，那他就会自动被添加到全局上下文。
            声明会被拿到函数或者全局作用域的顶部，位于作用域所有代码之前。这个现象叫做提升（hoisting）。
            2.let：块级作用域的由最近一对包含花括号{}界定。
                let 与 var的另一个不同之处是在一个作用域中不能声明两次。重复声明的var会被忽略，重复的let声明会抛出SyntaxError
                let非常适合在循环中声明变量。严格来讲，let也会被提升，但是由于暂时性死区，实际上不能在声明之前使用let变量。
            3.const：声明变量的时候必须初始化值。const给原始值赋值后则不能改变是常量。const给引用值赋值，无法改变引用路径，但是可以改变对象的键值。
                如果想让整个对象都不能修改，可以使用Object.freezs()
                const ob = Object.freezs()；ob.name = 1; console.log(ob.name) // undefined
            4.标识符查找
                当在特定的上下文中为了读取或写入引用一个标识符，必须通过搜索确定这个标识符表示什么。
                搜索开始于作用域前端，以给定的名称搜索标识符。如果在局部上下文中找到了这个标识符则搜索停止，变量确定。
                意思就是全局一个color变量，局部一个color变量，会先识别就近的局部变量，找到了就停了，不会再查全局的。
                注意：访问局部变量比访问全局变量要快，因为不用切换作用域。但是js对标识符查找上做了很多优化，这个性能优化可以忽略。
*/
this.a = '全局作用域a'

const c = () => {
    const c = 'c级作用域'
    console.log(this.a,'c1')
    console.log(a, 'c2')
    console.log(c)
}
function b() {
    this.a = 'b级作用域'
    const b = 'b级作用域'
    console.log(this.a,'b1')
    console.log(this.b,'this.b2')
    console.log(a,'b3')
    console.log(b)
}
function ff() {
    this.a = 'f级作用域'
    const b = 'f级作用域'
    console.log(this.a,'f1')
    console.log(this.b,'f2')
    console.log(a,'f3')
    console.log(b)
}
function aa() { 
    this.a = 'a级作用域'
    this.b = 'a级作用域中的this.b'
    const d = () => {
        const d = 'd级作用域'
        console.log(this.a,'d1')
        console.log(a, 'd2')
        console.log(d)
    }
    d();
    c();
    b();
}
aa();
ff();
